package managers.messengerManager;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import managers.conversationManager.ConversationManager;
import managers.messengerManager.services.PeriodicService;
import managers.messengerManager.services.Service;
import utils.ManagingMessage;
import utils.ManagingMessage.Type;
import utils.UserData;
import utils.UserState;

public class MessengerManager {

	private static MessengerManager sharedInstance = new MessengerManager();

	private boolean parametersSet = false;
	private int userId;
	private UserState state = UserState.AVAILABLE;
	private InetAddress serverAddress;
	private int serverPort;
	
	private HashMap<String, Service> services = new HashMap<String, Service>();
	private HashMap<String, PeriodicService> periodicServices = new HashMap<String, PeriodicService>();
	
	private FeedbackManager feedbackManager;
	private SingleProtocol protocol;
	private BroadcastProtocol broadcastProtocol;
	private DataManager dataManager;
	private UsersManager usersManager;

	private ConversationManager convManager = ConversationManager.getSharedInstance();

	private boolean recentFeedbackFromServer = true;

	
	private MessengerManager () {	
	}

	
	public void setParameters (int userId, String serverAddress, int serverPort, DataManager dataManager,
			FeedbackManager feedbackManager, UsersManager usersManager, SingleProtocol protocol, BroadcastProtocol broadcastProtocol) throws UnknownHostException {
		
		this.userId = userId;
		this.serverAddress = InetAddress.getByName(serverAddress);
		this.serverPort = serverPort;
		
		this.dataManager = dataManager;
		this.feedbackManager = feedbackManager;
		this.usersManager = usersManager;
		this.protocol = protocol;
		this.broadcastProtocol = broadcastProtocol;
		
		parametersSet = true;
	}
	
	public void start () throws Exception {
		
		if (parametersSet == false)
			throw new MessengerInitializingException("Parameters not set. Set the parameters before starting messenger.");
		
		dataManager.retrieveUsers();
		dataManager.retrievePersonalMessage();
		protocol.initialize();
		broadcastProtocol.initialize();
		
		UserData user = dataManager.getUser(userId);
		user.putProperty("ipAddress", protocol.getAddress());
		user.putProperty("port", protocol.getPort());
		
		Collection<Service> s = services.values();
		Iterator<Service> it = s.iterator();
		while (it.hasNext()) {
			it.next().start();
		}
			
		Collection<PeriodicService> ps = periodicServices.values();
		Iterator<PeriodicService> it2 = ps.iterator();
		while (it2.hasNext()) {
			PeriodicService temp = it2.next();
			new java.util.Timer().schedule(temp, 0, temp.getPeriod());
		}
		feedbackManager.update();
	}
	
	public void closeConnection() throws Exception {
		ManagingMessage request = new ManagingMessage(Type.LOGOFF_REQUEST);
		request.putProperty("userId", MessengerManager.getSharedInstance().getUserId());
		protocol.send(request, serverAddress, serverPort);
		protocol.closeSockets();
		convManager.close();
	}
	

	public int getUserId() {
		return userId;
	}
	
	public UserState getState() {
		return state;
	}
	
	public void setState(UserState state) {
		this.state = state;
	}
	
	public InetAddress getServerAddress() {
		return serverAddress;
	}


	public int getServerPort() {
		return serverPort;
	}


	public void addService (Service service) {
		services.put(service.getName(), service);
	}

	public void addPeriodicService (PeriodicService periodicService) {
		periodicServices.put(periodicService.getName(), periodicService);
	}
	

	public FeedbackManager getFeedbackManager() {
		return feedbackManager;
	}


	public SingleProtocol getSingleProtocol() {
		return protocol;
	}
	
	public BroadcastProtocol getBroadcastProtocol() {
		return broadcastProtocol;
	}


	public DataManager getDataManager() {
		return dataManager;
	}

	public UsersManager getUsersManager() {
		return usersManager;
	}

	public Service getService(String name) {
		return services.get(name);
	}


	public static MessengerManager getSharedInstance() {
		return sharedInstance;
	}


	public boolean getRecentFeedbackFromServer() {
		return recentFeedbackFromServer ;
	}
	
	public void setRecentFeedbackFromServer(boolean recent) {
		recentFeedbackFromServer = recent;
	}


}
